use tokio::net::{TcpStream, TcpListener};
use mini_redis::{Connection, Frame};
use mini_redis::Command::{self, Get, Set};
use std::collections::HashMap;

#[tokio::main]
async fn main() {
    println!("Hello, mini redis!");
    let addr = "127.0.0.1:8081".to_string();
    let listener = TcpListener::bind(&addr).await.expect("bind failed!");
    println!("listen on {}", addr);

    loop {
        let (tcp_straeam,socket_addr) = listener.accept().await.expect("accept failed!");
        tokio::spawn(async move {
            process(tcp_straeam).await;
        });
    }
}

async fn process(tcp_stream: TcpStream) {
    let mut db = HashMap::new();
    let mut connection = Connection::new(tcp_stream);

    while let Some(frame) = connection.read_frame().await.unwrap() {
        let response = match Command::from_frame(frame).unwrap() {
            Set(cmd) => {
                db.insert(cmd.key().to_string(), cmd.value().to_vec());
                Frame::Simple("OK".to_string())
            }
            Get(cmd) => {
                if let Some(value) = db.get(cmd.key()) {
                    Frame::Bulk(value.clone().into())
                } else {
                    Frame::Null
                }
            }
            cmd => panic!("unimplemented {:?}", cmd),
        };
        connection.write_frame(&response).await.unwrap();
    }
}
